import getopt
import os
import shutil
import subprocess
import sys
import time
import traceback

from ConfigParser import SafeConfigParser

from RpmExtractor import RpmExtractor
from Doc4 import *
from XmlDataLoader import *
from Component import *
from Archive import *
from File import *
from Constraint import *

class ExtractionManager(Doc4):
    
    def __init__(self):
        Doc4.__init__(self)
        self.logpath = self.config.get("extraction", "logfile")
        self.extractiondir = self.config.get("extraction", "outputdir")
        self.repositorydir = self.config.get("extraction", "mirror")
        self.extractorhome = self.config.get("extraction", "scriptdir")
        self.extractionskip = eval(self.config.get("extraction", "skipifextracted"))
        mapper(Component, self.schema.component_table)
        mapper(Archive, self.schema.archive_table)
        mapper(File, self.schema.file_table)
        mapper(Constraint, self.schema.constraint_table)
        
    def extract(self):
        #don't treat two times the same package in the same run or the result of the last attempt will override the previous results
        #e.g. "skipped" will override any potential previous error during the extraction itself
        done = []
        for repository_id in self.repository_ids:
            queue_query = self.config.get("extraction", "queue_query") % repository_id
            result = self.execute_sql(queue_query)
            repository = self.get_repository(repository_id) 
            for row in result:
                archive_file = row['file']
                id_snapshot = row['id_snapshot']
                mirror_dir = "%s/%s/%s/%s/%s/%s/" % (self.repositorydir, repository.provider, repository.distribution, repository.architecture, repository.branch, repository.section)
                output_dir = "%s/%d/%s/" % (self.extractiondir, self.string_to_integer(archive_file), archive_file)
                metadata_file = os.path.join(output_dir,'metadata.xml')
                    
                #useful for tests
                maxsize = (int) (self.config.get("extraction", "maxsize"))
                flag = False
                if maxsize is not None:
                    try:
                        if (os.path.exists(mirror_dir + archive_file)):
                            size = os.path.getsize(mirror_dir + archive_file)
                            big =  size > maxsize
                            flag = done.__contains__(archive_file) or big
                    except Exception, e:
                        self.log("Error: %s " % str(e))
                        traceback.print_exc(file=sys.stdout)
                        flag = False
                else:
                    flag = done.__contains__(archive_file)    
                if not flag:
                    if (os.path.exists(metadata_file)):
                        if (self.extractionskip):
                            try:
                                self.log("Metadata %s exists already -> skipping" % metadata_file)
                                self.set_package_state(archive_file, "extraction", "end_time", "skipped", "")
                                self.load_data(id_snapshot, metadata_file)
                            except Exception, e:
                                self.log("Error: %s " % str(e))
                                self.set_package_state(archive_file, "load", "end_time", "failed", str(e))

                        else:
                            result = shutil.rmtree(output_dir)
                            print "Dir %s removal... Result: %s" % (output_dir, result)
                            self.log("deletion of %s: %s" % (output_dir, result))
                            #if (not result):
                            #    set_package_state(archive_file, "end_date", "finished", "the already existing extraction folder could not be deleted")
                    
                    if (not os.path.exists(metadata_file)):
                            try:
                                pacx = RpmExtractor()
                                self.set_package_state(archive_file, "extraction", "start_time", "started", "")
                                self.log("Extracting: %s into %s..." % (mirror_dir + archive_file, output_dir))
                                extraction_result = pacx.extract_package(mirror_dir + archive_file, output_dir, False, repository_id, repository.branch, repository.section, self.extractorhome, self.logpath)
                                self.log("Result: %s " % extraction_result)
                            
                                if (extraction_result == 0):
                                    self.set_package_state(archive_file, "extraction", "end_time", "finished", "")

                                self.load_data(id_snapshot, metadata_file)
                                #pkg_file_path = os.path.join(mirror_dir,archive_file)
                                #os.remove(pkg_file_path)
    
                            except Exception, e:
                                self.log("Error: %s " % str(e))
                                self.set_package_state(archive_file, "extraction", "end_time", "failed", str(e))

                    done.append(archive_file)
    
    def load_data(self, id_snapshot, metadata_file):        
        loader = XmlDataLoader()
        loader.load_metadata(id_snapshot, metadata_file)

def main():
    exx = ExtractionManager()
    exx.extract()
        
if __name__ == "__main__":
    main()
    